package com.ideal.license.signer.manager;

import com.ideal.license.core.exception.CheckParamException;
import com.ideal.license.core.model.BaseComputerModel;
import com.ideal.license.core.model.LicenseModel;
import com.ideal.license.core.util.LicenseManagerHolder;
import de.schlichtherle.license.*;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;

import javax.security.auth.x500.X500Principal;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.logging.Logger;
import java.util.prefs.Preferences;

/**
 * 证书签名管理.
 */
public class LicenseSigner {
    private static final Logger logger = Logger.getLogger(LicenseSigner.class.getName());
    private static final String RSA="RSA";
    private static final String DSA="DSA";
    private static final String USER = "user";
    private static final String SYSTEM = "system";

    private final static X500Principal DEFAULTHOLDERANDISSUER =
            new X500Principal("CN=feilong, OU=feilong, O=feilong, L=SH, ST=SH, C=CN");

    /**
     * 新建证书.
     * @param model
     */
    public String createLicense(LicenseModel model) throws Exception {
        this.checkParam(model);
        this.initContent(model);

        LicenseManager licenseManager = LicenseManagerHolder.getLicenseManager(initParam(model));
        String fileName = model.getLicPath() + "/" + DateFormatUtils.format(new Date(), "yyyyMMddhhmmssSS") + ".lic";
        File licFile = new File(fileName);

        if ("".equals(model.getKeyAlg()) || DSA.equals(model.getKeyAlg())) {
            licenseManager.store(initContent(model),licFile, false );
        } else {
            licenseManager.store(initContent(model),licFile, true );
        }

        logger.info("license create success");

        return fileName;
    }

    /**
     * 初始化licenseParam.
     * @return
     */
    private LicenseParam initParam(LicenseModel model) {

        Preferences preferences = Preferences.systemNodeForPackage(this.getClass());
        CipherParam cipherParam = new DefaultCipherParam(model.getStorePass());
        KeyStoreParam keyStoreParam = new DefaultKeyStoreParam(this.getClass(),model.getPriPath(), model.getAlias(),
                model.getStorePass(), model.getKeyPass(), model.getKeyAlg());
        LicenseParam licenseParam = new DefaultLicenseParam(model.getSubject(), preferences, keyStoreParam, cipherParam);

        return licenseParam;
    }


    /*
     * 封装LicenseContent.
     * @param model
     * @return
     */
    private LicenseContent initContent(LicenseModel model) throws Exception {
        LicenseContent content = new LicenseContent();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

        content.setSubject(model.getSubject());
        content.setHolder(DEFAULTHOLDERANDISSUER);
        content.setIssuer(DEFAULTHOLDERANDISSUER);
        content.setIssued(model.getIssued());
        content.setNotBefore(sdf.parse(model.getNotBefore()));
        content.setNotAfter(sdf.parse(model.getNotAfter()));
        content.setConsumerType(model.getConsumerType());
        content.setConsumerAmount(model.getConsumerAmount());
        content.setExtra(model);

        logger.info("license content init success");

        return content;
    }

    /**
     * 验证参数.
     * @param model
     */
    private void checkParam(LicenseModel model) throws Exception {
        String[] algs = {RSA, DSA};
        String[] types = {"user", "system"};

        if (StringUtils.isBlank(model.getAlias())) {
            throw new CheckParamException("alias is null");
        }

        if (StringUtils.isBlank(model.getKeyAlg())) {
            throw new CheckParamException("keyAlg is null");
        }

        if (!ArrayUtils.contains(algs, model.getKeyAlg())) {
            throw new CheckParamException("keyAlg can only be RSA or DSA");
        }

        if (StringUtils.isBlank(model.getConsumerType())) {
            throw new CheckParamException("consumerType is null");
        }

        if (!ArrayUtils.contains(types, model.getConsumerType())) {
            throw new CheckParamException("consumerType can only be user or system");
        }

        if (null == model.getConsumerAmount() || model.getConsumerAmount() <= 0) {
            throw new CheckParamException("consumerAmount is null or <= 0");
        }

        if (StringUtils.isBlank(model.getEdition())) {
            throw new CheckParamException("edition is null");
        }

        if (StringUtils.isBlank(model.getKeyPass())){
            throw new CheckParamException("keyPass is null");
        }

        if (StringUtils.isBlank(model.getLicPath())) {
            throw new CheckParamException("licPath is null");
        }

        if (StringUtils.isBlank(model.getPriPath())) {
            throw new CheckParamException("priPath is null");
        }

        if (StringUtils.isBlank(model.getStorePass())) {
            throw new CheckParamException("storePass is null");
        }

        if (StringUtils.isBlank(model.getNotBefore())) {
            throw new CheckParamException("notBefore is null");
        }

        if (StringUtils.isBlank(model.getBaseComputerModel().getCPUSerial())) {
            throw new CheckParamException("CPU SN is null");
        }

        if (StringUtils.isBlank(model.getBaseComputerModel().getHardDiskSN())) {
            throw new CheckParamException("DISK SN is null");
        }

        if (StringUtils.isBlank(model.getBaseComputerModel().getIpAddress())){
            throw new CheckParamException("IP is null");
        }

        if (StringUtils.isBlank(model.getBaseComputerModel().getIpMacAddress())) {
            throw new CheckParamException("MAC is null");
        }

        if (StringUtils.isBlank(model.getBaseComputerModel().getMotherboardSN())) {
            throw new CheckParamException("mother board is null");
        }

        if (StringUtils.isBlank(model.getBaseComputerModel().getSystemSN())) {
            throw new Exception("SYSTEM SN is null");
        }

        logger.info("check param success");
    }

    private LicenseModel getLinux() {
        LicenseModel model = new LicenseModel();
        BaseComputerModel computerModel = new BaseComputerModel();
        computerModel.setCPUSerial("To Be Filled By O.E.M.,To Be Filled By O.E.M.");
        computerModel.setHardDiskSN("002d82e5270e4eac2051fa0200f02bc9,006a745e2b484eac2051fa0200f02bc9");
        computerModel.setIpAddress("192.168.102.107");
        computerModel.setIpMacAddress("8C:89:A5:7F:A9:E4,8C:89:A5:7F:A9:E5");
        computerModel.setMotherboardSN("To be filled by O.E.M.");
        computerModel.setSystemSN("211471150");
        model.setSubject("feilong lic");
        model.setConsumerAmount(1);
        model.setConsumerType("user");
        model.setInfo("this is first my lic");
        model.setNotAfter("2018-09-11");
        model.setNotBefore("2017-10-15");
        model.setBaseComputerModel(computerModel);
        model.setAlias("feilong");
        model.setKeyAlg("RSA");
        model.setLicPath("/usr/local/license/server/");
        model.setPriPath("/usr/local/license/server/feilong.keystore");
        model.setKeyPass("key123456");
        model.setStorePass("store123456");

        return model;
    }

    private LicenseModel getWin() {
        LicenseModel model = new LicenseModel();
        BaseComputerModel computerModel = new BaseComputerModel();
        computerModel.setCPUSerial("To Be Filled By O.E.M.,To Be Filled By O.E.M.");
        computerModel.setHardDiskSN("002d82e5270e4eac2051fa0200f02bc9,006a745e2b484eac2051fa0200f02bc9");
        computerModel.setIpAddress("192.168.102.107");
        computerModel.setIpMacAddress("8C:89:A5:7F:A9:E4,8C:89:A5:7F:A9:E5");
        computerModel.setMotherboardSN("To be filled by O.E.M.");
        computerModel.setSystemSN("211471150");
        model.setSubject("feilong lic");
        model.setInfo("this is first my lic");
        model.setNotAfter("2018-09-11");
        model.setNotBefore("2017-10-15");
        model.setBaseComputerModel(computerModel);
        model.setLicPath("D:\\key\\server");
        model.setPriPath("D:\\key\\server\\feilong.keystore");
        model.setKeyPass("key123456");
        model.setStorePass("store123456");
//        model.setEdition(LicenseConstant.NORAML_EDITION);

        return model;
    }

    public static void main(String[] args) {
        LicenseSigner signerLicenseManager = new LicenseSigner();

        LicenseModel model = signerLicenseManager.getWin();

        try{
//            signerLicenseManager.initContent(model);
            signerLicenseManager.createLicense(model);
//
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
